//
// * Copyright (c) 2002-2010 "Neo Technology,"
// *     Network Engine for Objects in Lund AB [http://neotechnology.com]
// *
// * This file is part of Neo4j.
// * 
// * Neo4j is free software: you can redistribute it and/or modify
// * it under the terms of the GNU Affero General Public License as
// * published by the Free Software Foundation, either version 3 of the
// * License, or (at your option) any later version.
// * 
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// * GNU Affero General Public License for more details.
// * 
// * You should have received a copy of the GNU Affero General Public License
// * along with this program. If not, see <http://www.gnu.org/licenses/>.
// 
namespace org.neo4j.kernel
{


	using GraphDatabaseService = org.neo4j.graphdb.GraphDatabaseService;

///
/// <summary> * Can start and stop a shell server via reflection if the shell should happen
/// * to be on the classpath, else it will gracefully say that it isn't there. </summary>
/// 
	internal class ShellService
	{
		private readonly GraphDatabaseService graphDb;
		private readonly object shellServer;

//JAVA TO VB & C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: ShellService(GraphDatabaseService neo, Map<String,Serializable> config) throws ShellNotAvailableException, RemoteException
		internal ShellService(GraphDatabaseService neo, Map<string, Serializable> config)
		{
			this.graphDb = neo;
			if (!shellDependencyAvailable())
			{
				throw new ShellNotAvailableException();
			}
			this.shellServer = startShellServer(config);
		}

		private bool shellDependencyAvailable()
		{
			try
			{
				System.Type.GetType("org.neo4j.shell.ShellServer");
				return true;
			}
			catch (System.Exception t)
			{
				return false;
			}
		}

//JAVA TO VB & C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private Object startShellServer(Map<String,Serializable> config) throws RemoteException
		private object startShellServer(Map<string, Serializable> config)
		{
			int port = (int) getConfig(config, "port", "DEFAULT_PORT");
			string name = (string) getConfig(config, "name", "DEFAULT_NAME");
			try
			{
//JAVA TO VB & C# CONVERTER TODO TASK: Java wildcard generics are not converted to .NET:
//ORIGINAL LINE: Class<?> shellServerClass = Class.forName("org.neo4j.shell.kernel.GraphDatabaseShellServer");
				System.Type<?> shellServerClass = System.Type.GetType("org.neo4j.shell.kernel.GraphDatabaseShellServer");
				object shellServer = shellServerClass.getConstructor(typeof(GraphDatabaseService)).newInstance(graphDb);
				shellServer.GetType().getMethod("makeRemotelyAvailable", int.TYPE, typeof(string)).invoke(shellServer, port, name);
				return shellServer;
			}
			catch (Exception e)
			{
				throw new RemoteException("Couldn't start shell '" + name + "' at port " + port, e);
			}
		}

//JAVA TO VB & C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private Serializable getConfig(Map<String,Serializable> config, String key, String defaultVariableName) throws RemoteException
		private Serializable getConfig(Map<string, Serializable> config, string key, string defaultVariableName)
		{
			Serializable result = config.get(key);
			if (result == null)
			{
				try
				{
					result = (Serializable) System.Type.GetType("org.neo4j.shell.impl.AbstractServer").getDeclaredField(defaultVariableName).get(null);
				}
				catch (Exception e)
				{
					throw new RemoteException("Default variable not found", e);
				}
			}
			return result;
		}

//JAVA TO VB & C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public boolean shutdown() throws ShellNotAvailableException
		public virtual bool shutdown()
		{
			try
			{
				shellServer.GetType().getMethod("shutdown").invoke(shellServer);
				return true;
			}
			catch (Exception e)
			{
			// TODO Really swallow this? Why not, who cares?
				return false;
			}
		}

		internal class ShellNotAvailableException : Exception
		{
			public ShellNotAvailableException() : base()
			{
			}
		}
	}
}